package labox.innovation.gameserver.model;

import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import labox.innovation.config.Config;
import labox.innovation.gameserver.datatables.EventDroplist;
import labox.innovation.gameserver.datatables.EventDroplist.DateDrop;
import labox.innovation.gameserver.model.actor.L2Attackable;
import labox.innovation.gameserver.model.actor.L2Character;
import labox.innovation.gameserver.model.actor.L2Summon;
import labox.innovation.gameserver.model.actor.L2Trap;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance;
import labox.innovation.gameserver.model.actor.instance.FuzePcInstance.KarmaStat;

import labox.innovation.gameserver.network.SystemMessageId;
import labox.innovation.gameserver.network.serverpackets.SystemMessage;
import labox.innovation.gameserver.templates.chars.NpcTemplate;
import labox.innovation.gameserver.templates.item.PcItemDropConfig;
import labox.innovation.util.Rnd;

/**
 *  掉落 流程管理
 *  管理所有物品掉落
 *  包括人物 和 怪物
 *  @author zjj
 *
 */
public class ItemDropManage {

	public static final Logger _log = LoggerFactory.getLogger(ItemDropManage.class.getName());

	protected static final int PC_PVP_STAT_FRIED = 1; //侠义状态  善恶值=[0,1000]

	protected static final int PC_PVP_STAT_EVIL = 2; //邪恶状态  善恶值=[-1000,-1]

	//侠义善恶值的 范围
	protected static final int _PVP_FRIED_MIN = 0;

	protected static final int _PVP_FRIED_MAX = 1000;

	//邪恶善恶值的范围
	protected static final int _PVP_EVIL_MIN = -1000;

	protected static final int _PVP_EVIL_MAX = -1;

	protected static final int PC_PVP_STAT_AGGRES = 3;
	
	public static final String DROP_STR = "怪物掉落";
	public static final String DROP_STR_PC = "角色掉落";
	public static final String DROP_STR_RAID = "掉落-团队分配";
	
	/**
	 * 是否物品掉落
	 * @param process
	 * @return
	 */
	public static boolean isDropItem( String process ){
		if( process.equals( DROP_STR ) || process.equals( DROP_STR_PC ) || process.equals( DROP_STR_RAID ) ){
			return true;
		}
		return false;
	}

	public static ItemDropManage getInstance() {
		return SingletonHolder._instance;
	}

	public final class RewardItem {
		protected int _itemId;

		protected int _count;

		public RewardItem(int itemId, int count) {
			_itemId = itemId;
			_count = count;
		}

		public int getItemId() {
			return _itemId;
		}

		public int getCount() {
			return _count;
		}
	}

	/**
	 * 
	 * @param lastAttacker : 攻击者
	 * @param killed :  被杀者
	 */
	public void dropItem(L2Character lastAttacker, L2Character killed) {
		if (killed instanceof L2Attackable) {
			
			dropItemAttackable(lastAttacker, (L2Attackable) killed);
		} else if (killed instanceof FuzePcInstance) {
			dropItemPc(lastAttacker, (FuzePcInstance) killed);
		}
	}

	/**
	 * 角色掉落
	 * @param killer 攻击者  
	 * @param killed 被杀者
	 */
	private void dropItemPc(L2Character killer, FuzePcInstance killed) {
//		if (killed.atEvent || killer == null)
//			return;
	
		if ( killer == null )
			return;
		
		FuzePcInstance pk = killer.getActingPlayer();
		if (pk == null) {
			return;
		}

		int iEquipDropNums = 0; //装备掉落数(装备在人身上的)
		int iDropItemNums = 0; //背包物品掉落数
		
		if ( killed.getKarmaStat() == KarmaStat.ERRANTRY ) { //如果 被杀者 是侠义 且 凶手 和死者 是同族 那么不掉落
			if (pk.getRace() == killed.getRace()) {
				//TODO:
				if( _log.isDebugEnabled() )
					_log.debug("同种族侠义不掉装备");
			} else { //异族侠义 死者 掉落装备的数量
				iEquipDropNums = PcItemDropConfig.getInstance().getDropEquipItemNums(PC_PVP_STAT_FRIED);
				iDropItemNums = PcItemDropConfig.getInstance().getDropItemNums(PC_PVP_STAT_FRIED);
			}
		}
		//被杀者 是邪恶的
		else if ( killed.getKarmaStat() == KarmaStat.EVIL ) {
			iEquipDropNums = PcItemDropConfig.getInstance().getDropEquipItemNums(PC_PVP_STAT_EVIL);
			iDropItemNums = PcItemDropConfig.getInstance().getDropItemNums(PC_PVP_STAT_EVIL);
		}
		//被杀着是 侵袭状态
		else {
			//TODO:
			//需要完成
			iEquipDropNums = PcItemDropConfig.getInstance().getDropEquipItemNums(PC_PVP_STAT_AGGRES);
			iDropItemNums = PcItemDropConfig.getInstance().getDropItemNums(PC_PVP_STAT_AGGRES);
		}

		//下面2个值 为了测试
//		iEquipDropNums = 0;
//		iDropItemNums = 2;

		if( _log.isDebugEnabled()){
			_log.debug(killed.getName() + "装备掉落数量:" + iEquipDropNums + "背包插槽掉数量:" + iDropItemNums );
		}
		
		//装备在人身上的装备掉落
		List<Integer> temp = killed.getInventory().getAllEquipedSolts();
		int slotNums = temp.size();
		
		if( _log.isDebugEnabled() ){
			_log.debug("角色身上的装备数: " + slotNums);
		}

		//如果有装备 装备的情况下
		if (slotNums > 0) {
			while (iEquipDropNums> 0) {
				int slotNumb = temp.get(Rnd.get(slotNums));
				L2ItemInstance item = killed.getInventory().getPaperdollItem(slotNumb);
				if( item != null && !item.isBinding() ){
//					if( killed.dropItem("被杀掉落装备", item, killed, true) != null )
//						killed.getInventory().getAllEquipItems()[slotNumb] = null;
					killed.dropItem("被杀掉落装备", item, killed, true);
					iEquipDropNums--;
				}
				if (item != null)
					pk.addItem(DROP_STR_PC, item, killed, true);

				temp.remove((Integer) slotNumb);
				slotNums = temp.size();

				if (slotNums <= 0) {
					break;
				}

			}// end 

		}// end if( slotNums > 0 )

		temp = killed.getInventory().getAllInventoryItemedSlots();
		slotNums = temp.size();

		if( _log.isDebugEnabled() ){
			_log.debug("角色背包里的装备数: " + slotNums);
		}
		
		//背包格子物品掉落, 按格子掉落
		if (slotNums > 0) {
			while (iDropItemNums-- > 0) {
				int slotNumb = temp.get(Rnd.get(slotNums));
				if( _log.isDebugEnabled() ){
					_log.debug("格子物品数: " + slotNums);
					_log.debug("格子索引: " + slotNumb);
				}

				L2ItemInstance item = killed.dropItem("掉落背包物品", slotNumb, killed, true);
				if (item != null)
					pk.addItem(DROP_STR_PC, item, killed, true);

				temp.remove((Integer) slotNumb);
				slotNums = temp.size();

				if (slotNums <= 0) {
					break;
				}

			}// end while( iDropItemNums-- > 0 )

		}// end if( slotNums > 0 )

	}// end dropItemPc

	/**
	 *  怪物 物品掉落
	 * @param lastAttacker
	 * @param killed
	 */
	private void dropItemAttackable(L2Character lastAttacker, L2Attackable killed) {
		FuzePcInstance player = lastAttacker.getActingPlayer();
		if (player == null) {
			_log.warn("攻击者不是玩家,不掉了物品", Config.SERVER_ID);
			return;
		}

		NpcTemplate npcTemplate = killed.getTemplate();

		if (npcTemplate.getDropData() != null) {
			for (FuzeDropCategory cat : npcTemplate.getDropData()) {//遍历掉落的道具模板
				RewardItem item = null;
				//获得掉落列表 的掉落数量
				int dropNums = calculateDropNums(lastAttacker, cat);
				
				if( _log.isDebugEnabled() ){
					_log.debug( "此掉落列表的掉落数量为:" + dropNums );
				}
				
				//获得掉落列表的 随机区间范围.(所有物品掉落几率之和)
				int ichancerange = cat.getCategoryChance();
				if( _log.isDebugEnabled() ){
					_log.debug( "掉落列表里所有物品掉落总概率为:" + ichancerange );
				}
				
				//从掉落列表中 掉落出 相应的物品 数量
				while (dropNums-- > 0) {
					item = calculateCategorizedRewardItem(player, killed, cat, ichancerange);
				
					if (item != null) {
						if (_log.isDebugEnabled())
							_log.debug("Item id to drop: " + item.getItemId() + " amount: " + item.getCount());

						//检查掠夺模式（直接放入背包）是否开启
						//						if ((!killed.isRaid() && Config.AUTO_LOOT) || (killed.isRaid() && Config.AUTO_LOOT_RAIDS))
						//							player.doAutoLoot(killed, item); //直接给杀了此对象的玩家道具
						//						else
						//							dropItem(player, item); //掉落道具在地上

						
						player.doAutoLoot(killed, item); //直接给杀了此对象的玩家道具

						//广播一条消息，通知raidboss被击败了
						if (killed.isRaid() && !killed.isRaidMinion()) {
							SystemMessage sm;
							sm = new SystemMessage(SystemMessageId.C1_DIED_DROPPED_S3_S2);
							sm.addCharName(killed);
							sm.addItemName(item.getItemId());
							sm.addItemNumber(item.getCount());
							killed.broadcastPacket(sm);
						}// end 

					}// end 	if (item != null)

				}// end while( dropNums-- > 0 )

			}// end for (L2DropCategory cat : npcTemplate.getDropData())

		}// end if (npcTemplate.getDropData() != null) 
		else {
			_log.warn("怪物身上不存在掉了列表", Config.SERVER_ID);
		}

		//:TODO: 暂时先屏蔽
		//		//其他特殊事件的物品掉落
		//		//
		//		dropEventItem( lastAttacker, killed );

	}// end dropItemAttackable

	/**
	 * 处理特殊事件的 物品掉落
	 * @param lastAttacker
	 * @param killed
	 */
	private void dropEventItem(L2Character lastAttacker, L2Attackable killed) {
		FuzePcInstance player = null;

		if (lastAttacker instanceof FuzePcInstance)
			player = (FuzePcInstance) lastAttacker;
		else if (lastAttacker instanceof L2Summon)
			player = ((L2Summon) lastAttacker).getOwner();
		else if (lastAttacker instanceof L2Trap)
			player = ((L2Trap) lastAttacker).getOwner();

		// Don't drop anything if the last attacker or owner isn't L2PcInstance
		if (player == null)
			return;

		if (player.getLevel() - killed.getLevel() > 9)
			return;

		// Go through DateDrop of EventDroplist allNpcDateDrops within the date range
		for (DateDrop drop : EventDroplist.getInstance().getAllDrops()) {
			if (Rnd.get(FuzeDropData.MAX_CHANCE) < drop.chance) {
				RewardItem item = new RewardItem(drop.items[Rnd.get(drop.items.length)], Rnd.get(drop.min, drop.max));

				if (Config.AUTO_LOOT)
					player.doAutoLoot(killed, item); //把道具给杀死这个对象的玩家
				else
					dropItem(player, item); //把道具掉落在地上
			}
		}
	}

	/**
	 * 掉落物品 在地上
	 * 鉴于 现不会d掉落在地上 暂不实现
	 * @param player
	 * @param item
	 * @return
	 */
	private L2ItemInstance dropItem(FuzePcInstance player, RewardItem item) {
		return null;
	}

	/**
	 *  计算掉落列表的掉落 数量
	 *  掉落列表 的格式为 num:chance(2:1000)
	 *  总的chance和为10000
	 * @param categoryDrops : 掉落列表
	 * @return
	 */
	private int calculateDropNums(L2Character lastAttacker, FuzeDropCategory categoryDrops) {
		List<FuzeDropCategoryDrop> temp = categoryDrops.getAllDropNum();

//		int ichance = Rnd.get(10001);
		double fchance = Rnd.nextDouble();
		int ichance = (int) (fchance * 10000);
//		int ichance = Rnd.get(100) + 1;
//		ichance *= Rnd.get(100) + 1;
		if( _log.isDebugEnabled() ){
			_log.debug("掉路列表的掉落数量概率:" + ichance);
		}

		int dropnums = 0;

		//概率范围
		int minchance = 0;
		int maxchance = 0;
//		System.out.println("掉落几率:" + ichance);
		for (FuzeDropCategoryDrop fuzeDropcd : temp) {

			maxchance += fuzeDropcd.getChance();

			if (ichance >= minchance && ichance <= maxchance) {
//				System.out.println("模板配置掉落数量:" + fuzeDropcd.getNum());
				dropnums = fuzeDropcd.getNum();
				break;
			}

			minchance = maxchance;

		}

		FuzePcInstance pcplayer = lastAttacker.getActingPlayer();
		if (pcplayer != null) {
			
			//关于组队部分的 掉落数量的修正 和 个人掉落系数 掉落数量的修正
			L2Party party = pcplayer.getParty();
			if( party != null )
			{
				//随机分配
				if( party.getLootDistribution() == L2Party.ITEM_RANDOM )
				{
					dropnums = (int) (dropnums * pcplayer.getTemplate().getBaseItemAmountRate() + Config.ITEMDROPNUMS);
				}
				else{
					float totalnums = 0;
					for( FuzePcInstance tempPc : party.getPartyMembers() )
					{
						totalnums += tempPc.getTemplate().getBaseItemAmountRate();
					}
					totalnums = totalnums / party.getMemberCount();
					
					dropnums = (int) (dropnums * totalnums + Config.ITEMDROPNUMS);
				}
			}

			return dropnums;
		}

		return 0;
	}

	/**
	 * 计算物品的掉落类型 和 数
	 * @param lastAttacker
	 * @param killed
	 * @param categoryDrops
	 * @param ichancerange  : 物品掉落概率总和
	 * @return
	 */
	private RewardItem calculateCategorizedRewardItem(FuzePcInstance lastAttacker, L2Attackable killed, FuzeDropCategory categoryDrops, int ichancerange) {
		List<FuzeDropData> allDrops = categoryDrops.getAllDrops();

		int idropchance = Rnd.get(ichancerange + 1);
		if( _log.isDebugEnabled() ){
			_log.debug("决定掉落某个物品的几率:" + idropchance );
		}

		//概率范围
		int minchance = 0;
		int maxchance = 0;
		for (FuzeDropData temp : allDrops) {
			maxchance += temp.getChance();

			if( _log.isDebugEnabled() ){
				_log.debug("掉落范围:" + minchance + "-" +  maxchance);
			}
			
			if (idropchance >= minchance && idropchance <= maxchance) {
				if( _log.isDebugEnabled() ){
					_log.debug("掉落物品id:" + temp.getItemId() + "掉落物品数量:" + temp.getItemCount() );
				}
				//返回掉落物品的信息。  每次物品都是掉一个
				return new RewardItem(temp.getItemId(), temp.getItemCount());
			}

			minchance = maxchance;

		}

		return null;
	}

	///////////////

	private static class SingletonHolder {
		protected static final ItemDropManage _instance = new ItemDropManage();
	}

	private ItemDropManage() {
	}

}// end ItemDropManage
